package com.heima.article.service.Imp;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.mapper.AuthorMapper;
import com.heima.article.service.ApArticleConfigService;
import com.heima.article.service.ApArticleContentService;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.GeneratePageService;
import com.heima.common.exception.CustException;
import com.heima.feigns.AdminFeign;
import com.heima.feigns.WemediaFeign;
import com.heima.model.admin.pojo.AdChannel;
import com.heima.model.article.dto.ArticleHomeDTO;
import com.heima.model.article.pojo.ApArticle;
import com.heima.model.article.pojo.ApArticleConfig;
import com.heima.model.article.pojo.ApArticleContent;
import com.heima.model.article.pojo.ApAuthor;
import com.heima.model.article.vos.HotArticleVo;
import com.heima.model.common.constants.article.ArticleConstants;
import com.heima.model.common.constants.message.NewsUpOrDownConstants;
import com.heima.model.common.constants.wemedia.WemediaConstants;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojo.ApUser;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.threadlocal.AppThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle> implements ApArticleService {
    @Autowired
    private AdminFeign adminFeign;
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private AuthorMapper authorMapper;
    @Autowired
    private ApArticleConfigService apArticleConfigService;
    @Autowired
    private ApArticleContentService apArticleContentService;
    @Autowired
    private GeneratePageService generatePageService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public ResponseResult loadFromCache(Short loadtype, ArticleHomeDTO dto) {
        //取redis查询数据
        String jsonStr = redisTemplate.opsForValue().get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());
        //如果查询结果为空
        if (StringUtils.isBlank(jsonStr)) {
            //查询数据库
            return load(loadtype,dto);
        }
        //将字符串转为集合
        List<HotArticleVo> hotArticleVoList = JSON.parseArray(jsonStr, HotArticleVo.class);
        if (CollectionUtils.isEmpty(hotArticleVoList)) {
            //查询数据库
            load(loadtype,dto);
        }
        //封面在前端不显示 需要拼接路径
        for (HotArticleVo hotArticleVo : hotArticleVoList) {
            String images = hotArticleVo.getImages();
            if (StringUtils.isNotBlank(images)) {
           images = Arrays.stream(images.split(","))
                   .map(url -> webSite + url).collect(Collectors.joining(","));
           hotArticleVo.setImages(images);
            }
           // hotArticleVo.setStaticUrl(readPath + hotArticleVo.getStaticUrl());
        }

        return ResponseResult.okResult();
    }

    /**
     * 发布文章
     * @param newsId
     */
    @Override
    public void PublishArticle(Integer newsId) {
        //1.根据文章id查询自媒体信息
        WmNews wmNews =  getWmNews(newsId);
        //2.根据wmnews信息封装apArticle对象
        ApArticle apArticle = getApArticle(wmNews);
        //3.保存修改apArticle对象
        saveOrUpdateArticle(apArticle);
        //4.保存配置信息和内容信息
        saveContentAndConfig(apArticle,wmNews);
        //TODO 5.页面静态化
       generatePageService.generateArticlePage(wmNews.getContent(),apArticle);
        //6.修改wmNews的状态 将状态修改为9 设置相关的article id
        updateWmNews(apArticle,wmNews);
        //7.TODO MQ更新es索引
        rabbitTemplate.convertAndSend(NewsUpOrDownConstants.NEWS_UP_FOR_ES_QUEUE,apArticle.getId());
        log.info("成功发送索引库更新消息文章id{}" + apArticle.getId());

    }

    /**
     * 根据id获取文章信息
     * @param newsId
     * @return
     */

    private WmNews getWmNews(Integer newsId) {
        //对id进行判空
        if (newsId == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"传入的id不能为空");
        }
        ResponseResult<WmNews> responseResult = wemediaFeign.selectById(newsId);
        //检查远程调用是否正确
        if (!responseResult.checkCode()) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"远程调用失败");
        }
        WmNews wmNews = responseResult.getData();
        //将获得的对象进行判空
        if (wmNews == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"查询的文章不存在");
        }
        //检查文章的状态 必须是4或者8
        if (!WemediaConstants.WM_NEWS_AUTHED_STATUS.equals(wmNews.getStatus())&& !WemediaConstants.WM_NEWS_AUTH_PASS.equals(wmNews.getStatus())) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_ALLOW,"文章不是通过审核状态!");
        }
        return wmNews;
    }

    /**
     * 将wmNews抄到ApArticle
     * @param wmNews
     * @return
     */
    private ApArticle getApArticle(WmNews wmNews) {
        //创建ApArticle对象
        ApArticle article = new ApArticle();
        //将相同的属性抄过来
        BeanUtils.copyProperties(wmNews,article);
        //将文章的Id重新设置
        article.setId(wmNews.getArticleId());
        article.setLayout(wmNews.getType());
        article.setFlag((byte)0);
        //设置author的信息
        ApAuthor author = authorMapper.selectOne(Wrappers.<ApAuthor>lambdaQuery().eq(ApAuthor::getWmUserId, wmNews.getUserId()));
        if (author == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"作者信息不存在");
        }
        article.setAuthorId(Long.valueOf(author.getId()));
        article.setAuthorName(author.getName());
        //设置channel的信息
        ResponseResult<AdChannel> responseResult = adminFeign.findOne(wmNews.getChannelId());
        //对远程调用进行校验
        if (!responseResult.checkCode()) {
            log.error("文章发布失败 远程调用查询频道出现异常， 不予发布 , 文章id : {}  频道id : {}",wmNews.getId(),wmNews.getChannelId());
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR,"远程调用查询频道出现异常");
        }
        //获取对应的频道数据
        AdChannel channel = responseResult.getData();
        if (channel == null) {
            log.error("文章发布失败 未查询到相关频道信息， 不予发布 , 文章id : {}  频道id : {}",wmNews.getId(),wmNews.getChannelId());
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"未查询到相关频道信息");
        }
        article.setChannelId(channel.getId());
        article.setChannelName(channel.getName());

        return article;
    }

    /**
     * 保存修改文章信息
     * @param apArticle
     */
    private void saveOrUpdateArticle(ApArticle apArticle) {
        //判断原先文章是否保存过
        if (apArticle.getId() == null) {
            //文章不存在
            apArticle.setComment(0);
            apArticle.setCollection(0);
            apArticle.setLikes(0);
            apArticle.setViews(0);
            this.save(apArticle);
        } else {
            //文章原先存在 删除原先的关联关系
            ApArticle article = getById(apArticle.getId());
            if (article == null) {
                CustException.cust(AppHttpCodeEnum.PARAM_INVALID,"文章不存在");
            }

            //删除原先配置中的id
            apArticleConfigService.remove(Wrappers
                    .<ApArticleConfig>lambdaUpdate()
                    .eq(ApArticleConfig::getArticleId,article.getId()));
            //删除原先内容中的id
            apArticleContentService.remove(Wrappers
                    .<ApArticleContent>lambdaUpdate()
                    .eq(ApArticleContent::getArticleId,article.getAuthorId()));
            //保存原先的内容
            updateById(article);

        }
    }
    @Autowired
    private ApArticleConfigMapper apArticleConfigMapper;
    @Autowired
    private ApArticleContentMapper apArticleContentMapper;
    /**
     * 保存文章关联的内容信息和配置信息
     * @param apArticle
     * @param wmNews
     */
    private void saveContentAndConfig(ApArticle apArticle, WmNews wmNews) {
        //封装内容信息
        ApArticleContent content = new ApArticleContent();
        content.setArticleId(apArticle.getId());
        content.setContent(wmNews.getContent());
        apArticleContentMapper.insert(content);
        //封装文章配置信息
        ApArticleConfig config = new ApArticleConfig();
        config.setArticleId(apArticle.getId());
        config.setIsComment(true);
        config.setIsForward(true);
        config.setIsDown(false);
        config.setIsDelete(false);
        apArticleConfigMapper.insert(config);
    }
    /**
     * 修改状态为9实现发布
     * @param apArticle
     * @param wmNews
     */
    private void updateWmNews(ApArticle apArticle, WmNews wmNews) {
        wmNews.setStatus(WemediaConstants.WM_NEWS_PUBLISH_STATUS);
        wmNews.setArticleId(apArticle.getId());
        ResponseResult<WmNews> responseResult = wemediaFeign.updateWmNews(wmNews);
        if (!responseResult.checkCode()) {
            log.error("远程修改状态发布文章失败");
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
    }

    @Autowired
    private ApArticleMapper apArticleMapper;
    @Value("${file.oss.web-site}") //直接从配置中动态读取
    String webSite;
    @Value("${file.minio.readPath}")
    private String readPath;
    /**
     * app端查询文章列表信息
     * @param type
     * @param dto
     * @return
     */
    @Override
    public ResponseResult load(short type, ArticleHomeDTO dto) {
        //1.判断数据是否为空
        if (dto == null) {
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"数据不存在");
        }
        //3.判断页码是否为空
        if (dto.getSize() == null) {
            dto.setSize(10);
        }

        //5.判断最大时间是否为空
        if (dto.getMinBehotTime() == null) {
            dto.setMinBehotTime(new Date());
        }
        //4.判断最小时间是否为空
        if (dto.getMaxBehotTime() == null) {
            dto.setMaxBehotTime(new Date());
        }

        //6判断整合请求的类型
        if (!(ArticleConstants.LOADTYPE_LOAD_MORE.equals(type)) && !(ArticleConstants.LOADTYPE_LOAD_NEW.equals(type))) {
            type = ArticleConstants.LOADTYPE_LOAD_MORE;
        }
        //7对数据频道ID进行判断
        if (dto.getTag() == null) {
            dto.setTag(ArticleConstants.DEFAULT_TAG);
        }
        //8.查询符合条件的文章信息
        List<ApArticle> list = apArticleMapper.findList(dto,type);
        //遍历集合
        for (ApArticle apArticle : list) {
            String images = apArticle.getImages();
            if (StringUtils.isNotEmpty(images)) {
                String[] imageList = images.split(",");
                //对文章的路径进行处理
                String urlNeed = Arrays.stream(imageList)
                        .map(url -> webSite + url)
                        .collect(Collectors.joining(","));
                apArticle.setImages(urlNeed);
            }
            /*apArticle.setStaticUrl(readPath + apArticle.getStaticUrl());*/
        }

        return ResponseResult.okResult(list);
    }
}